#ifndef __CGEN_H
#define __CGEN_H 1

#include <pcode.h>
#include <stack>
#include <generator.h>
#include <unordered_map>
#include <algorithm>

#include <scope.h>

struct Status {
    bool ok;
    std::string true_label;
    std::string false_label;
    std::string continue_label;
    std::string exit_label;
};

class  Cgen : public Generator {
public:
    Scope scope;

    std::vector<Pcode> program;
    std::vector<Pcode> codes;
    std::stack<Status> status;
    int _label = 0;

    std::string label() { return Sprintf(".L%d", _label++);}
    void push_status(bool ok) { status.push({ok, label(), label(), label(), label()});}
    void pop_status() { status.pop();}

    std::stack<int> reg;
    size_t used, max_used;
    std::string return_label;

    void function_init(FunctionStat *ptr);
    void function_deinit();

    int pop() { int r = reg.top(); reg.pop(); 
        if (r != v0) {used++; max_used = std::max(max_used, used);}
        return r;}
    void push(int r) { reg.push(r); used--;}


    std::vector<std::string> content;
    void gen(BlockStat* ptr) override;
    void gen(ReturnStat* ptr) override;
    void gen(IfStat* ptr) override;

    void gen(UnaryOpStat* ptr) override;
    void gen(BinaryOpStat* ptr) override;
    void gen(TernaryOpStat* ptr) override;

    void gen(NameStat* ptr) override;
    void gen(LiteralIntegerStat* ptr) override;

    void gen(ParamStat *ptr) override;
    void gen(FunctionStat* ptr) override;

    void gen(VariableStat *ptr) override;
    void gen(VariableDefineStat* ptr) override;

    void gen(ForStat* ptr) override;

    void gen(StructStat *ptr) override;

    void gen(VarStat *ptr) override;

    void gen(GotoStat *ptr) override;

    void gen(WhileStat *ptr) override;
    void gen(DoWhileStat *ptr) override;
    void gen(BreakStat *ptr) override;
    void gen(ContinueStat *ptr) override;
    void gen(LabelStat *ptr) override;

    virtual void genType(Type ptr) override;
};

#endif // __CGEN_H
